home *** CD-ROM | disk | FTP | other *** search
- Xref: bloom-picayune.mit.edu comp.lang.lisp:8753 comp.lang.clos:1593 news.answers:4563
- Path: bloom-picayune.mit.edu!enterpoop.mit.edu!spool.mu.edu!uunet!ogicse!das-news.harvard.edu!cantaloupe.srv.cs.cmu.edu!crabapple.srv.cs.cmu.edu!mkant
- From: mkant+@cs.cmu.edu (Mark Kantrowitz)
- Newsgroups: comp.lang.lisp,comp.lang.clos,news.answers
- Subject: FAQ: CLOS and PCL Questions 5/6 [Monthly posting]
- Summary: Questions about CLOS, PCL and object-oriented programming in Lisp
- Message-ID: <lisp-faq-5.text_724237355@cs.cmu.edu>
- Date: 13 Dec 92 09:03:06 GMT
- Article-I.D.: cs.lisp-faq-5.text_724237355
- Expires: Tue, 26 Jan 1993 09:02:35 GMT
- Sender: news@cs.cmu.edu (Usenet News System)
- Reply-To: lisp-faq@think.com
- Followup-To: poster
- Organization: School of Computer Science, Carnegie Mellon
- Lines: 237
- Approved: news-answers-request@MIT.Edu
- Supersedes: <lisp-faq-5.text_721645367@cs.cmu.edu>
- Nntp-Posting-Host: a.gp.cs.cmu.edu
-
- Archive-name: lisp-faq/part5
- Last-Modified: Thu Nov 5 19:30:40 1992 by Mark Kantrowitz
- Version: 1.27
-
- ;;; ****************************************************************
- ;;; Answers to Frequently Asked Questions about Lisp ***************
- ;;; ****************************************************************
- ;;; Written by Mark Kantrowitz and Barry Margolin
- ;;; lisp-faq-5.text -- 11959 bytes
-
- This post contains Part 5 of the Lisp FAQ. It is cross-posted to the
- newsgroup comp.lang.clos because it contains material of interest to
- people concerned with CLOS, PCL and object-oriented programming in
- Lisp. The other parts of the Lisp FAQ are posted only to the
- newsgroups comp.lang.lisp and news.answers.
-
- If you think of questions that are appropriate for this FAQ, or would
- like to improve an answer, please send email to us at lisp-faq@think.com.
-
- CLOS/PCL Questions (Part 5):
-
- [5-0] What is CLOS (PCL) and where can I get it?
- How do you pronounce CLOS?
- [5-1] What documentation is available about object-oriented
- programming in Lisp?
- [5-2] How I write a function that can access defstruct slots by
- name? I would like to write something like
- (STRUCTURE-SLOT <object> '<slot-name>).
- [5-3] How can I list all the CLOS instances in a class?
- [5-4] How can I store data and CLOS instances (with possibly circular
- references) on disk so that they may be retrieved at some later
- time?
- [5-5] Given the name of a class, how can I get the names of its slots?
-
- Search for [#] to get to question number # quickly.
-
- In general, questions about object oriented programming in Lisp,
- especially questions about using CLOS or compiling PCL, should be
- directed to the newsgroup comp.lang.clos.
-
- ----------------------------------------------------------------
- [5-0] What is CLOS (PCL) and where can I get it?
- How do you pronounce CLOS?
-
- CLOS (Common Lisp Object System) is the object-oriented programming
- standard for Common Lisp. It is the successor to Symbolics FLAVORS and
- Xerox LOOPS (Lisp Object Oriented Programming System). The acronym
- CLOS is pronouned either as "See-Loss" or "Closs", depending on taste.
- PCL (Portable Common Loops) is a portable CLOS implementation, and is
- available by anonymous ftp from parcftp.xerox.com (13.1.64.94) in the
- /pub/pcl/ directory. Also in the same directory are sources for CLX R5
- and an inspecter.
-
- The sources for the CLOS Metaobject Protocol specification are
- also available from parcftp as /pub/pcl/mop/spec.tar.Z. See also the book
- ``The Art of the Metaobject Protocol'' below. The Closette files
- related to this book are available from parcftp as /pub/pcl/mop/closette.lisp.
-
- ----------------------------------------------------------------
- [5-1] What documentation is available about object-oriented
- programming in Lisp?
-
- Books about object-oriented programming in Lisp include:
-
- 1. dpANS CL describes the entire Common Lisp language, which includes the
- CLOS standard. Informally, CLtL2 can also be used to learn about CLOS,
- but please remember that CLtL2 is not an official X3J13 committee
- document. (The presentation of CLtL2 differs from that of the draft
- proposed standard, and some matters of fact have changed in the proposed
- standard since the publication of CLtL2.)
-
- 2. Sonya E. Keene
- "Object-Oriented Programming in Common Lisp:
- A Programmer's Guide to CLOS"
- Addison-Wesley (Reading, MA), 1989. 266 pages. ISBN 0-201-17589-4.
- Tutorial introduction to CLOS with many examples and
- a lot of good advice for designing large programs using CLOS.
-
- 3. Jo A. Lawless and Molly M. Miller.
- "Understanding CLOS: the Common Lisp Object System"
- Digital Press, 1991. 192 pages.
-
- 4. Gregor Kiczales, Jim des Rivieres, and Daniel G. Bobrow.
- "The Art of the Metaobject Protocol"
- MIT Press, 1991. 335 pages. ISBN 0-262-61074-4
- The first part of the book presents a model CLOS implementation,
- introduces the basic principles of metaobject protocols, and
- works through the key elements of the CLOS Metaobject Protocol.
- The second half is the detailed specification of the CLOS
- Metaobject Protocol. A simple working interpreter suitable
- for experimentation is contained in an appendix.
-
- 5. Robert R. Kessler and Amy R. Petajan.
- "LISP, Objects, and Symbolic Programming"
- Scott, Foresman and Company (Glenview, IL), 1988. 644 pages.
- Includes a small Lisp compiler.
- ----------------------------------------------------------------
- [5-2] How can I write a function that can access defstruct slots by name? I
- would like to write something like
- (STRUCTURE-SLOT <object> '<slot-name>).
-
- There is currently no portable, built-in way to access structure slots
- given only the name. If your Common Lisp includes an implementation
- of CLOS that supports the meta-object protocol specified in the
- original X3J13 draft spec (document X3J13/88-003), then it probably will
- allow (SLOT-VALUE <object> '<slot-name>); however, not all
- implementations of CLOS currently provide this. Lacking this, some
- implementations may provide implementation-dependent functions that
- allow access to structure slots by name; note that this may cause
- saved images to be larger, as some implementations normally open-code
- structure accessors and discard slot name information.
-
- While it is not possible to write a fully general STRUCTURE-SLOT function,
- it is not very difficult to write version that handles specific structure
- types. For instance, after defining:
-
- (defstruct spaceship name captain position velocity)
-
- one may then define:
-
- (defun spaceship-slot (spaceship slot-name)
- (ecase slot-name
- (name (spaceship-name spaceship))
- (captain (spaceship-captain spaceship))
- (position (spaceship-position spaceship))
- (velocity (spaceship-velocity spaceship))))
-
- or using CLOS (generic functions):
-
- (defgeneric spaceship-slot (spaceship slot-name)
- (:method ((x spaceship) (slot (eql :name)))
- (spaceship-name x))
- (:method ((x spaceship) (slot (eql :captain)))
- (spaceship-captain x))
- (:method ((x spaceship) (slot (eql :position)))
- (spaceship-position x))
- (:method ((x spaceship) (slot (eql :velocity)))
- (spaceship-velocity x)))
-
- Another popular way to define this is:
-
- (defun spaceship-slot (spaceship slot-name)
- (funcall (symbol-function
- (find-symbol (format nil "SPACESHIP-~A" slot-name)
- #.(package-name *package*)))
- spaceship))
-
- I personally recommend the first version. It is likely to be much faster
- and more memory efficient than the second version. It's also easy to get
- the second one wrong; many people forget to specify the package argument to
- FIND-SYMBOL, which can cause incorrect results when the package at run time
- is different from the one at compile time. Even my version assumes that
- SPACESHIP-SLOT is being defined in a file that is in the same package as
- the one containing the structure definition; if this isn't the case,
- #.(PACKAGE-NAME *PACKAGE*) should be replaced by a string naming the
- correct package.
-
- Another workaround is to define a MY-DEFSTRUCT macro that parses the
- defstruct arguments and expands into a call to DEFSTRUCT along with a
- definition of the runtime slot-accessor function.
-
- Some non-portable techniques include the use of LCL:STRUCTURE-REF
- in Lucid and EXCL:STRUCTURE-REF in Allegro.
- ----------------------------------------------------------------
- [5-3] How can I list all the CLOS instances in a class?
-
- There is no built-in way to enumerate the instances of a class. If you are
- only interested in listing the instances of classes that you have defined,
- it is not very difficult to implement it as part of your class definition.
- Add a shared slot, e.g. ALL-INSTANCES, with an initial value of NIL, to the
- class definition. Then write an after-method on INITIALIZE-INSTANCE for
- this class, which pushes the instance being initialized onto ALL-INSTANCES.
- Note that this must be done separately for each class that wants to maintain
- such a list; it can't be encapsulated in a mixin class, because all its
- dependent classes would share the same ALL-INSTANCES slot. A compromise
- would be to use a mixin to define the INITIALIZE-INSTANCE after-method (and
- any other general-purpose methods that use the slot), but not the shared
- slot; it would be up to the descendant classes to define the slot at the
- level of the class hierarchy that is appropriate. You could also try
- defining the classes that need instance-recording as instances of a
- metaclass that holds the instance registry on the class object. The
- recording behavior could then be built-in to an after method on
- initialize-instance for the root class of the metaclass, or even
- allocate-instance. To allow for garbage collection of old instances,
- you will also need to define a generic function to remove the recorded
- instances from the list of instances.
- ----------------------------------------------------------------
- [5-4] How can I store data and CLOS instances (with possibly circular
- references) on disk so that they may be retrieved at some later
- time?
-
- There are two main techniques of doing this kind of persistent object
- storage. The first involves using #. to compile the data into a file.
- The second produces an ASCII representation which, when evaluated,
- will reproduce an equivalent set of data.
-
- If the data you wish to save is stored in the variable *hash-table*,
- create a file containing just the lines
- (in-package "YOUR-PACKAGE")
- (setq *hash-table* '#.*hash-table*)
- and compile it. The #. macro performs read-time evaluation of the
- expression following the dot, and so this compiles the data into the
- file. You may then load the file to restore the data. However, the
- resulting binary file is not portable between Lisp implementations,
- and sometimes not even for the same Lisp on different platforms. Also,
- some Lisps will treat the data as constant, and place it on pages in
- memory that are marked read-only (after it is loaded). If one tries to
- later modify the data, these Lisps will signal an error. Lucid CL only
- puts such constants in a read-only area when they appear inside
- functions, so this should be safe. Allegro CL doesn't seem to complain
- about modification if the data is a cons. DEC's VAXLisp, however, has
- problems with #. circular structures in .fas files.
-
- The other technique is to produce an ASCII representation of the Lisp
- objects which may then be saved to a file. To reproduce the data, one
- can load (or compile and load) the file. This technique is portable
- between different Lisps and platforms. Unfortunately, the resulting
- data is not necessarily EQ to the original. Kerry Koitzsch's
- save-object.lisp package is included in the Lisp Utilities Repository,
- ftp.cs.cmu.edu:/afs/cs.cmu.edu/user/mkant/Public/Lisp-Utilities/.
- (Note: You must cd to this directory in one atomic operation, as some
- of the superior directories on the path are protected from access by
- an anonymous ftp.) The Lisp Utilities Repository is described in
- detail in the answer to question [6-1].
-
- See also the discussion of MAKE-LOAD-FORM and MAKE-LOAD-FORM-SAVING-SLOTS
- in CLtL2.
-
- ----------------------------------------------------------------
- [5-5] Given the name of a class, how can I get the names of its slots?
-
- (defun class-slot-names (class-name)
- (mapcar #'clos:slot-definition-name
- (clos:class-slots (find-class class-name))))
-
- ----------------------------------------------------------------
- ;;; *EOF*
-